const qiniu = require('qiniu') // https://developer.qiniu.com/kodo/1731/api-overview
const log = require('../log')
const packageJson = require('../package.json')

const UPLOAD = {}

// 七牛云 response code  https://developer.qiniu.com/kodo/3928/error-responses
const UPLOAD_CODE = {
  400: '请求报文格式错误',
  401: '认证授权失败',
  404: '资源不存在',
  405: '请求方式错误',
  406: '上传的数据 CRC32 校验错误',
  413: '请求资源大小大于指定的最大值',
  419: '用户账号被冻结',
  478: '镜像回源失败',
  502: '错误网关',
  503: '服务端不可用',
  504: '服务端操作超时',
  573: '单个资源访问频率过高',
  579: '上传成功但是回调失败',
  599: '服务端操作失败',
  608: '资源内容被修改',
  612: '指定资源不存在或已被删除',
  614: '目标资源已存在',
  630: '已创建的空间数量达到上限，无法创建新空间',
  631: '指定空间不存在',
  640: '调用列举资源(list)接口时，指定非法的marker参数',
  701: '在断点续上传过程中，后续上传接收地址不正确或ctx信息已过期'
}

// 获取七牛token
UPLOAD.token = (options) => {
  const putPolicy = new qiniu.rs.PutPolicy({ scope: options.bucket })
  const accessKey = options.accessKey
  const secretKey = options.secretKey
  const mac = new qiniu.auth.digest.Mac(accessKey, secretKey)
  const uploadToken = putPolicy.uploadToken(mac)
  return uploadToken
}

// 获取七牛mac
UPLOAD.mac = (options) => {
  return new qiniu.auth.digest.Mac(options.accessKey, options.secretKey)
}

// 打印响应日志
UPLOAD.responseLog = (type, options, fileName, respErr, respInfo) => {
  let msgType = ''
  switch (type) {
  case 'Upload':
    msgType = 'green'
    break
  case 'Delete':
    msgType = 'yellow'
    break
  default:
    msgType = 'blue'
    break
  }
  if (respErr) {
    log.red(`${packageJson.name} ${type} Error ${options.prefix}/${fileName}`)
    log.red(`${packageJson.name} ${type} Error>> ${respErr}`)
  }
  if (respInfo && respInfo.statusCode === 200) {
    log[msgType](`${type} Success ${options.prefix}/${fileName}`)
  } else if (respInfo) {
    log.red(`${packageJson.name} ${type} Error ${options.prefix}/${fileName}`)
    log.red(`${packageJson.name} ${type} Error>> ${respInfo.statusCode} ${UPLOAD_CODE[respInfo.statusCode] ? UPLOAD_CODE[respInfo.statusCode] : ''}`)
  }
}

// 上传
UPLOAD.upload = (file, options, fileName) => {
  const token = UPLOAD.token(options) // 生成上传 Token
  const formUploader = new qiniu.form_up.FormUploader(options)
  const putExtra = new qiniu.form_up.PutExtra()
  formUploader.putFile(token, fileName, file.path, putExtra, (respErr, respBody, respInfo) => {
    if (respErr) {
      log.red(`${packageJson.name} Upload Error ${options.prefix}/${fileName}`)
      log.red(`${packageJson.name} Upload Error>> ${respErr}`)
    }
    if (respInfo && respInfo.statusCode === 200) {
      log.green(`Upload Success ${options.prefix}/${fileName}`)
    } else if (respInfo) {
      log.red(`${packageJson.name} Upload Error ${options.prefix}/${fileName}`)
      log.red(`${packageJson.name} Upload Error>> ${respInfo.statusCode} ${UPLOAD_CODE[respInfo.statusCode] ? UPLOAD_CODE[respInfo.statusCode] : ''}`)
    }
  })
}

/**
 * 获取指定前缀的文件列表
 * @param {String} bucket bucket
 * @param {Object} options 配置
 * @param {Object} params 参数
 *  prefix    string 列举的文件前缀
 *  marker    string 上一次列举返回的位置标记，作为本次列举的起点信息
 *  limit     number 每次返回的最大列举文件数量
 *  delimiter string 指定目录分隔符
 * @param {Function} options 回调
 */
UPLOAD.get = (bucket, options, params, callback) => {
  const config = new qiniu.conf.Config()
  config.zone = qiniu.zone[options.region] // 需对应区域
  const bucketManager = new qiniu.rs.BucketManager(UPLOAD.mac(options), config)
  bucketManager.listPrefix(bucket, params, (respErr, respBody, respInfo) => {
    if (respErr) {
      log.red(`${packageJson.name} Get Error>> ${respErr}`)
    }
    if (respInfo && respInfo.statusCode === 200) {
      callback(respBody.items)
    } else {
      log.red(`${packageJson.name} Get Error>> ${respInfo.statusCode} ${UPLOAD_CODE[respInfo.statusCode] ? UPLOAD_CODE[respInfo.statusCode] : ''}`)
    }
  })
}

/**
 * 删除
 * @param {Object} options 配置
 * @param {String} fileName 文件地址列表
 */
UPLOAD.delete = (options, fileName) => {
  const config = new qiniu.conf.Config()
  config.zone = qiniu.zone[options.region] // 需对应区域
  const bucketManager = new qiniu.rs.BucketManager(UPLOAD.mac(options), config)
  bucketManager.delete(options.bucket, fileName, (respErr, respBody, respInfo) => {
    if (respErr) {
      log.red(`${packageJson.name} Delete Error>> ${respErr}`)
    }
    if (respInfo && respInfo.statusCode === 200) {
      log.yellow(`Delete Success ${options.prefix}/${fileName}`)
    } else {
      log.red(`${packageJson.name} Delete Error>> ${respInfo.statusCode} ${UPLOAD_CODE[respInfo.statusCode] ? UPLOAD_CODE[respInfo.statusCode] : ''}`)
    }
  })
}

module.exports = UPLOAD